import csv
import re
import pdb
from collections import defaultdict

def autotype( str ):
    try:
        return int(str)
    except ValueError:
        pass
    try:
        return float(str)
    except ValueError:
				return str

def readResultsFile( fn ): 
	rxid = re.compile(r"[\\/](\d+)[^\\/]*\.jpg$");
	rxflipcol = re.compile('_flipcol_');

	reader = csv.DictReader(open(fn,'rb'))
	m = dict()

	for row in reader:
		if 'FILENAME$' in row:
			match = rxid.search( row['FILENAME$'] )
			if match:
				row['SceneID'] = match.group(1)

			if rxflipcol.search( row['FILENAME$'] ):
				row['FLIPCOL'] = 1;
			else:
				row['FLIPCOL'] = 0;

		for key in row:
			row[key] = autotype( row[key] )

		rkey = (row['CellID$'],row['Rep'],row['TrialNum'])

		if rkey not in m:
			m[rkey] = []
		m[rkey].append( row )
	return m

""" Returns a map, the first key is the CellID$, second SceneID, third (FADEOUT,FLIPCOL,OR3),
		and the last is the set number,
		the value is the firing rate

		Status of the presentation must be 0
"""
def calculateFiringRates(events,spikes):

	rates = defaultdict(lambda: defaultdict(lambda: defaultdict(dict) ))
	lookup = defaultdict(dict)
	for pkey in events:
		p = events[pkey][0]  # events are uniquely described by pkey
		if p['Status'] != 0:
			continue

		scene = p['SceneID']
		for key in ['SceneID','FADEOUT','OR3','FLIPCOL','Status','Set','FIGSIDE']:
			lookup[ p['CellID$'], p['Rep'], p['TrialNum'] ][key] = p[key];

	duration_s = dict();
	for trialkey in spikes:
		#print trialkey
		for s in spikes[trialkey]:
			if s['SpikeEvent'] == -1:
				duration_s[trialkey] = s['SpikeTime']/1000.0


	for trialkey in spikes:
		for s in spikes[trialkey]:
			if s['SpikeTime'] <= 0:
				continue
	
			cellid = s['CellID$']
			trialinfo = lookup[ cellid, s['Rep'], s['TrialNum'] ]
			if not trialinfo or trialinfo['Status'] != 0:
				continue

			if s['SpikeEvent'] != 1:
				#print s['SpikeTime'],
				continue
	
			scene = trialinfo['SceneID']
			imvar = ('','','');
			if trialinfo['FADEOUT']:
				imvar0 = 'entire'
			else:
				imvar0 = 'patch'
			if trialinfo['FLIPCOL']:
				imvar1 = 'normcol'
			else:
				imvar1 = 'flipcol'
			imvar = (imvar0,imvar1,trialinfo['OR3'])

			if trialkey not in rates[cellid][scene][imvar]:
				rates[cellid][scene][imvar][trialkey] = 0.0

			rates[cellid][scene][imvar][trialkey] += 1.0 / duration_s[trialkey]
		
	return rates,lookup

def analyzeRates( rates, trials ):
	counts = defaultdict(dict)
	avgrates = defaultdict(lambda: defaultdict( dict ))
	#pdb.set_trace();
	for cellid in rates:
		for scene in rates[cellid]:
			for imvar in rates[cellid][scene]:
				for trialkey in rates[cellid][scene][imvar]:
					# figure of side corrected for OR3
					#trialkey = (cellid,rep,trialnum)
					trial = trials[trialkey]
					if (trial['OR3'] + trial['FIGSIDE']+180)%360 < 180:
						figside1 = 0;
					else:
						figside1 = 1;
					imvar1 = (imvar[0],imvar[1],figside1)
	
					if cellid not in avgrates or imvar1 not in avgrates[cellid]:
						avgrates[cellid][imvar1] = 0.0
						counts[cellid][imvar1] = 0
	
					rate = rates[cellid][scene][imvar][trialkey]
					avgrates[cellid][imvar1] += rate
					counts[cellid][imvar1] += 1
		
	for cellid in avgrates:
		for imvar1 in avgrates[cellid]:
			avgrates[cellid][imvar1] = avgrates[cellid][imvar1] / counts[cellid][imvar1]

	
	bomod = defaultdict(dict) # border-ownership modulation
	print 'Cell\tBO Entire vs patch:'
	for cellid in avgrates:
		for region in ['entire','patch']:
			bomod[cellid][region] = (
				( avgrates[cellid][(region,'normcol',0)] - avgrates[cellid][(region,'normcol',1)] ) / 
				( avgrates[cellid][(region,'normcol',0)] + avgrates[cellid][(region,'normcol',1)] ))
		print '%s:\t%.4f\t%.4f'%(cellid,bomod[cellid]['entire'],bomod[cellid]['patch'])
			

	return avgrates,counts,bomod

def run():
	spikes = readResultsFile('/data/research/27a/27a_NaturalImages.spike.csv')
	events = readResultsFile('/data/research/27a/27a_NaturalImages.basic.csv')
	rates,trials = calculateFiringRates(events,spikes)

	avgrates,counts,bomod = analyzeRates( rates, trials )
	return bomod
	
